package com.chengyu.core.controller.callback;

import com.alibaba.fastjson.JSONObject;
import com.chengyu.core.controller.UserBaseController;
import com.chengyu.core.controller.callback.manager.CallbackManager;
import com.chengyu.core.domain.CommonConstant;
import com.chengyu.core.entity.CommonResult;
import com.chengyu.core.model.SysWeixinConfig;
import com.chengyu.core.service.pay.wxpay.WeixinRefundResponse;
import com.chengyu.core.util.weixin.WechatUtil;
import com.chengyu.core.utils.MD5Util;
import com.chengyu.core.utils.StringUtils;
import com.chengyu.core.utils.WechatAesUtil;
import com.wechat.pay.contrib.apache.httpclient.auth.CertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;


@Controller
public class RefundCallbackController extends UserBaseController {


	private Logger logger = LoggerFactory.getLogger(RefundCallbackController.class);

    private static Cipher cipher = null;  //解码器

	@Autowired
	private CallbackManager callbackManager;

	@Autowired
	private CallbackManager paySusManager;

	private CertificatesVerifier verifier;



	private String apiclientKey = "/www/wwwroot/ccchongya.com/wxpay/apiclient_key.pem";


	private String wechatPaySerial = "4AF8EF44563B5889AE7F4351BAFFBC4E030AFE1E";

	private String apiV3Key="zoILFM69fxQ5YSUnq3H2hHSW0jDKgNQv";



    public CommonResult<String> refundSusForZfb(HttpServletRequest request,HttpServletResponse response, String type) throws Exception{
    	//支付宝退款目前没有使用异步退款,无需回调
		return CommonResult.success(null);
    }

    public CommonResult<String> refundSusForWx(HttpServletRequest request, String type) throws Exception{
		//获取报文
		String body = getRequestBody(request);
		//随机串
		String nonceStr = request.getHeader("Wechatpay-Nonce");
		//微信传递过来的签名
		String signature = request.getHeader("Wechatpay-Signature");
		//证书序列号（微信平台）
		String serialNo = request.getHeader("Wechatpay-Serial");
		//时间戳
		String timestamp = request.getHeader("Wechatpay-Timestamp");
		//应答时间戳\n
		//应答随机串\n
		//应答报文主体\n
		String signStr = Stream.of(timestamp, nonceStr, body).collect(Collectors.joining("\n", "", "\n"));
		Map<String, String> map = new HashMap<>(2);

		String plainBody = decryptBody(body);
		logger.info("解密后的明文:{}", plainBody);
		Map<String, String> paramsMap = convertWechatRefundMsgToMap(plainBody);
		logger.info("paramsMap:{}", paramsMap);


		if(StringUtils.isNotBlank((String) paramsMap.get("amount_refund")) && CommonConstant.SUCCESS.equals(paramsMap.get("refund_status"))){
			//支付成功
//			logger.info("支付成功:{}");
			paySusManager.getPaySusFactory(type).refundSus((String) paramsMap.get("out_trade_no"));
		}


//		return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";

		return CommonResult.success(null);
    }

    public static void init() {
		SysWeixinConfig config = WechatUtil.config;
        String key = MD5Util.MD5Encode(config.getMchKey(), "");
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
        Security.addProvider(new BouncyCastleProvider());
        try {
            cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
    }



	/**
	 * 解密body的密文
	 *
	 * "resource": {
	 *         "original_type": "transaction",
	 *         "algorithm": "AEAD_AES_256_GCM",
	 *         "ciphertext": "",
	 *         "associated_data": "",
	 *         "nonce": ""
	 *     }
	 *
	 * @param body
	 * @return
	 */
//	@SneakyThrows
	private String decryptBody(String body) throws IOException, GeneralSecurityException {


		WechatAesUtil aesUtil = new WechatAesUtil(apiV3Key.getBytes(StandardCharsets.UTF_8));
//		WechatAesUtil aesUtil = new WechatAesUtil(wechatPayConfig.getApiV3Key().getBytes("utf-8"));

		JSONObject object = JSONObject.parseObject(body);
		JSONObject resource = object.getJSONObject("resource");
		String ciphertext = resource.getString("ciphertext");
		String associatedData = resource.getString("associated_data");
		String nonce = resource.getString("nonce");


		return aesUtil.decryptToString(associatedData.getBytes("utf-8"),nonce.getBytes("utf-8"),ciphertext);

	}

	/**
	 * 转换body为map
	 * @param plainBody
	 * @return
	 */
	private Map<String,String> convertWechatRefundMsgToMap(String plainBody){

		Map<String,String> paramsMap = new HashMap<>(2);

		JSONObject jsonObject = JSONObject.parseObject(plainBody);

		//商户订单号
		paramsMap.put("out_trade_no",jsonObject.getString("out_trade_no"));

		//交易状态
		paramsMap.put("refund_status",jsonObject.getString("refund_status"));




		JSONObject jsonObject2 = JSONObject.parseObject(jsonObject.getString("amount"));

		paramsMap.put("amount_refund",jsonObject2.getString("refund"));
		paramsMap.put("amount_total",jsonObject2.getString("total"));
		paramsMap.put("amount_payer_total",jsonObject2.getString("payer_total"));
		paramsMap.put("amount_payer_refund",jsonObject2.getString("payer_refund"));



		//附加数据
//		paramsMap.put("account_no",jsonObject.getJSONObject("attach").getString("accountNo"));

		return paramsMap;

	}




	/**
	 * 验证签名
	 *
	 * @param serialNo  微信平台-证书序列号
	 * @param signStr   自己组装的签名串
	 * @param signature 微信返回的签名
	 * @return
	 * @throws UnsupportedEncodingException
	 */
//	private boolean verifiedSign(String serialNo, String signStr, String signature) throws UnsupportedEncodingException {
//
//
//		return verifier.verify(serialNo, signStr.getBytes("utf-8"), signature);
//	}


	/**
	 * 读取请求数据流
	 *
	 * @param request
	 * @return
	 */
	private String getRequestBody(HttpServletRequest request) {

		StringBuffer sb = new StringBuffer();

		try (ServletInputStream inputStream = request.getInputStream();
			 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
		) {
			String line;

			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}

		} catch (IOException e) {
			logger.error("读取数据流异常:{}", e);
		}

		return sb.toString();

	}

	/**
	 * 获得验签器
	 * @return
	 * @throws Exception
	 */
	public Verifier verifier() throws Exception {
		SysWeixinConfig config = WechatUtil.config;
		//获取证书管理器实例
		CertificatesManager certificatesManager = CertificatesManager.getInstance();
		certificatesManager.putMerchant(config.getMchId(), new WechatPay2Credentials(config.getMchId(),new PrivateKeySigner(wechatPaySerial, getPrivateKey())), apiV3Key.getBytes(StandardCharsets.UTF_8));
		// 从证书管理器中获取verifier
		Verifier verifier = certificatesManager.getVerifier(config.getMchId());
		return verifier;
	}


	/**
	 * 获取商户证书私钥
	 *
	 * @return 私钥对象
	 */
	public PrivateKey getPrivateKey() throws IOException {
		SysWeixinConfig config = WechatUtil.config;
		PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new FileInputStream(apiclientKey));
		return merchantPrivateKey;
	}


}
